---
title: Subject
editUrl: https://github.com/toolbeam/openauth/blob/master/packages/openauth/src/subject.ts
description: Reference doc for creating subjects.
---

import { Segment, Section, NestedTitle, InlineSection } from 'toolbeam-docs-theme/components'
import { Tabs, TabItem } from '@astrojs/starlight/components'

<div class="tsdoc">
<Section type="about">
Subjects are what the access token generated at the end of the auth flow will map to. Under
the hood, the access token is a JWT that contains this data.

#### Define subjects

```ts title="subjects.ts"
import { object, string } from "valibot"

const subjects = createSubjects({
  user: object({
    userID: string()
  })
})
```

We are using [valibot](https://github.com/fabian-hiller/valibot) here. You can use any
validation library that's following the
[standard-schema specification](https://github.com/standard-schema/standard-schema).

:::tip
You typically want to place subjects in its own file so it can be imported by all of your apps.
:::

You can start with one subject. Later you can add more for different types of users.

#### Set the subjects

Then you can pass it to the `issuer`.

```ts title="issuer.ts"
import { subjects } from "./subjects"

const app = issuer({
  providers: { ... },
  subjects,
  // ...
})
```

#### Add the subject payload

When your user completes the flow, you can add the subject payload in the `success` callback.

```ts title="issuer.ts"
const app = issuer({
  providers: { ... },
  subjects,
  async success(ctx, value) {
    let userID
    if (value.provider === "password") {
      console.log(value.email)
      userID = ... // lookup user or create them
    }
    return ctx.subject("user", {
      userID
    })
  },
  // ...
})
```

Here we are looking up the userID from our database and adding it to the subject payload.

:::caution
You should only store properties that won't change for the lifetime of the user.
:::

Since these will be stored in the access token, you should avoid storing information
that'll change often. For example, if you store the user's username, you'll need to
revoke the access token when the user changes their username.

#### Decode the subject

Now when your user logs in, you can use the OpenAuth client to decode the subject. For
example, in our SSR app we can do the following.

```ts title="app/page.tsx"
import { subjects } from "../subjects"

const verified = await client.verify(subjects, cookies.get("access_token")!)
console.log(verified.subject.properties.userID)
```

All this is typesafe based on the shape of the subjects you defined.
</Section>
---
## Methods
### createSubjects
<Segment>
<Section type="signature">
```ts
createSubjects(types)
```
</Section>
<Section type="parameters">
#### Parameters
- <p><code class="key">types</code> [<code class="type">SubjectSchema</code>](/docs/subject#subjectschema)</p>
</Section>
<InlineSection>
**Returns** [<code class="type">SubjectSchema</code>](/docs/subject#subjectschema)
</InlineSection>
Create a subject schema.
```ts
const subjects = createSubjects({
  user: object({
    userID: string()
  }),
  admin: object({
    workspaceID: string()
  })
})
```


This is using [valibot](https://github.com/fabian-hiller/valibot) to define the shape of the
subjects. You can use any validation library that's following the
[standard-schema specification](https://github.com/standard-schema/standard-schema).
</Segment>
## SubjectSchema
<Segment>
<Section type="parameters">
<InlineSection>
**Type** <code class="primitive">Record</code><code class="symbol">&lt;</code><code class="primitive">string</code>, [<code class="type">v1.StandardSchema</code>](https://github.com/standard-schema/standard-schema)<code class="symbol">&gt;</code>
</InlineSection>
</Section>
Subject schema is a map of types that are used to define the subjects.
</Segment>
</div>